<?php
/*
 * MySql DB Wrapper for YappFramework
 *
 * Extends abstract classyappDBWrapper
 *
 */

class mysqlDBWrapper extends yappDBWrapper
{

    // Vars
    private $connected = false;
    public $handler   = false;

    // Create connection for only one time
    protected function connect()
    {
        if (!$this->connected)
        {
            $this->handler = new mysqli($this->hostName, $this->userName, $this->password);
            if ($this->handler->connect_errno) {
                error_log("Failed to connect to MySQL: (" . $this->handler->connect_errno . ") " . $this->handler->connect_error);
                die();
            }
        }
    }

    // Connect passively
    protected function checkConnection()
    {
        if (!$this->handler)
        {
            $this->connect();
        }
    }

    // Close connection
    public function closeConnection()
    {
        if ($this->handler)
        {
            $this->handler->close();
            $this->handler = false;
        }
    }

    // Select database engine own function
    protected function engineSetDatabase($database = false)
    {
        return $this->handler->select_db($database);
    }

    // Perform raw query
    protected function engineRawQuery($sql)
    {
        $return = $this->handler->query($sql);
        return $return;
    }

    // Get tables for this engine
    protected function engineGetTablesAndFields()
    {
        if ($tablesQuery = $this->engineRawQuery('SHOW TABLES;'))
        {
            $tables = array();
            while ($table = $this->fetchRow($tablesQuery))
            {
                // Get table fields
                if ($fieldsQuery = $this->engineRawQuery('SHOW COLUMNS FROM '.$table[0].';'))
                {
                    $tables[$table[0]] = array();
                    // Always make primary key array at first position
                    while ($field = $this->fetchRow($fieldsQuery))
                    {
                        if (strpos($field[1], 'int') !== false)
                        {
                            if ($field[3] == 'PRI')
                            {
                                $tables[$table[0]] = array($field[0] => FIELD_TYPE_INTEGER) + $tables[$table[0]];
                            }
                            else
                            {
                                $tables[$table[0]][$field[0]] = FIELD_TYPE_INTEGER;
                            }
                        }
                        else if (strpos($field[1], 'float') !== false)
                        {
                            if ($field[3] == 'PRI')
                            {
                                $tables[$table[0]] = array($field[0] => FIELD_TYPE_FLOAT) + $tables[$table[0]];
                            }
                            else
                            {
                                $tables[$table[0]][$field[0]] = FIELD_TYPE_FLOAT;
                            }
                        }
                        else
                        {
                            if ($field[3] == 'PRI')
                            {
                                $tables[$table[0]] = array($field[0] => FIELD_TYPE_STRING) + $tables[$table[0]];
                            }
                            else
                            {
                                $tables[$table[0]][$field[0]] = FIELD_TYPE_STRING;
                            }
                        }
                    }
                }
            }
            return $tables;
        }
        else
        {
            die("Error getting tables");
        }
    }

    // Fetch associative array
    protected function engineFetchAssoc($result)
    {
        if ($result)
        {
            return $result->fetch_assoc();
        }
        else
        {
            return false;
        }
    }

    // Fetch row in plain array
    protected function engineFetchRow($result)
    {
        if ($result)
        {
            return $result->fetch_row();
        }
        else
        {
            return false;
        }
    }

    // Return num rows from query result
    protected function engineNumRows($result)
    {
        if ($result)
        {
            return $result->num_rows;
        }
        else
        {
            return 0;
        }
    }

    // Affected rows
    protected function engineAffectedRows()
    {
        if ($this->handler)
        {
            return $this->handler->affected_rows;
        }
        else
        {
            return false;
        }
    }

    // Last insert id
    protected function engineInsertId()
    {
        if ($this->handler)
        {
            return $this->handler->insert_id;
        }
        else
        {
            return false;
        }
    }

    // Escape string
    protected function engineEscape($val)
    {
        $this->checkConnection();
        return $this->handler->real_escape_string($val);
    }

    // Offset and limit
    protected function engineOffsetAndLimit($totalOrOffset, $total)
    {
        return 'LIMIT '.intval($totalOrOffset).', '.intval($total);
    }

    // Transaction methods (only supported for INNODB tables!)
    protected function engineBeginTransaction()
    {
        $this->handler->autocommit(false);
    }
    protected function engineRollbackTransaction()
    {
        $this->handler->rollback();
    }
    protected function engineCommitTransaction()
    {
        $this->handler->commit();
    }

}
?>